package com.ledijiaoyu.autogate;

import android.app.Activity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;

import com.ledijiaoyu.autogate.base.AutoGateCommand;
import com.ledijiaoyu.autogate.base.AutoGatePacket;
import com.ledijiaoyu.autogate.packet.request.ForceGateAlwaysOpenPacket;
import com.ledijiaoyu.autogate.packet.request.ForceGateClosePacket;
import com.ledijiaoyu.autogate.packet.request.OnLineTestPacket;
import com.ledijiaoyu.autogate.packet.request.ReadCreditCardInfoPacket;
import com.ledijiaoyu.autogate.packet.request.ReadMachineMemoryPacket;
import com.ledijiaoyu.autogate.packet.request.SetCreditCardKeystorePacket;
import com.ledijiaoyu.autogate.packet.request.SoftOpenGatePacket;
import com.ledijiaoyu.autogate.packet.response.ReadCardInfoResponse;
import com.ledijiaoyu.autogate.packet.response.ReadMachineMemoryInfoResponse;
import com.ledijiaoyu.autogate.packet.response.ResponseHelper;
import com.ledijiaoyu.autogate.serialport.SerialPortReceiverListener;
import com.ledijiaoyu.autogate.serialport.SerialPortTunnel;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
import cn.dinkevin.xui.net.CustomErrorHandler;
import cn.dinkevin.xui.net.exception.ApiException;
import cn.dinkevin.xui.thread.ThreadExecutor;
import cn.dinkevin.xui.util.LogUtil;
import cn.dinkevin.xui.util.StringUtil;
import cn.dinkevin.xui.util.TimeUtil;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.schedulers.Schedulers;

public class MainActivity extends Activity implements SerialPortReceiverListener{


    @BindView(R.id.txt_console)
    public TextView txt_console;

    @BindView(R.id.edt_serialPortName)
    public EditText edt_name;

    @BindView(R.id.edt_serialBaudRate)
    public EditText edt_baudRate;

    private SerialPortTunnel mTunnel;
    private int mLastCardInfoId;

    private void appConsole(String msg){
        txt_console.append(TimeUtil.getCurrentTime() + ":" + msg + "\n");
        int offset = txt_console.getLineCount() * txt_console.getLineHeight();
        if(offset > txt_console.getHeight()) {
            txt_console.scrollTo(0, offset - txt_console.getHeight());
        }
    }


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ButterKnife.bind(this);

        ThreadExecutor.pool(() -> {
            while (true){
                if(LogUtil.mLogCache.isEmpty()) continue;
                String msg = LogUtil.mLogCache.remove(0);
                ThreadExecutor.main(() -> appConsole(msg));
            }
        });

        txt_console.setMovementMethod(ScrollingMovementMethod.getInstance());
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
        mTunnel.closeSerialPort();
    }


    @OnClick(R.id.btn_openSerialPort)
    public void onOpenSerialPort(View view){
        String serialPortName = edt_name.getText().toString();
        int serialBaudRate = Integer.parseInt(edt_baudRate.getText().toString());
        mTunnel = new SerialPortTunnel(serialPortName,serialBaudRate);
        mTunnel.openSerialPort();
        mTunnel.setReceiverListener(this);
    }


    @OnClick(R.id.btn_closeSerialPort)
    public void onCloseSerialPort(View view){
        mTunnel.closeSerialPort();
    }


    private static final int BUFFER_MAX =   1024;
    private byte[] mReceiveBuffer = new byte[BUFFER_MAX];
    private int mReceiveBufferPoint = 0;

    @Override
    public void onReceiveBuffer(byte[] buffer, int offset) {

        // 将接收到的数据缓存起来
        if(mReceiveBufferPoint + offset > BUFFER_MAX){
            mReceiveBufferPoint = 0;
        }
        System.arraycopy(buffer,0, mReceiveBuffer, mReceiveBufferPoint,offset);
        mReceiveBufferPoint += offset;

        // 判断数据包是否结束
        if(offset  > 0){

            byte tail = buffer[offset - 1];
            if(tail == AutoGatePacket.tail){

                // 取出缓存数据，同时清空缓存
                byte[] packet = new byte[mReceiveBufferPoint];
                System.arraycopy(mReceiveBuffer,0,packet,0,mReceiveBufferPoint);
                mReceiveBufferPoint = 0;

                Flowable.just(packet)
                        .subscribeOn(Schedulers.io())
                        .observeOn(AndroidSchedulers.mainThread())
                        .subscribe(data -> {

                            appConsole(String.format("receive [Hex]:%s",StringUtil.byte2Hex(data)));

                            String output = StringUtil.char2String(StringUtil.byte2Char(data));
                            appConsole(String.format("receive [Char]:%s",output));


                            ResponseHelper helper = new ResponseHelper(data);
                            String command = helper.getCommand();
                            if(StringUtil.isNotEmpty(command)){
                                if(command.equals(AutoGateCommand.RESPONSE_READ_GATE_MEMORY)){
                                    ReadMachineMemoryInfoResponse response = new ReadMachineMemoryInfoResponse();
                                    response.decode(data);
                                    appConsole(String.format("card information %d",response.getCardInformationCount()));
                                    mLastCardInfoId = response.getCardInformationCount();
                                }
                                else if(command.equals(AutoGateCommand.RESPONSE_READ_EVENT_INFORMATION)){
                                    ReadCardInfoResponse response = new ReadCardInfoResponse();
                                    response.decode(data);
                                    appConsole(String.format("card number %s",response.getCardNumber()));
                                }
                            }

                        }, new CustomErrorHandler<Throwable>() {

                            @Override
                            public void onError(ApiException e) {

                            }
                        });
            }
        }
    }

    @OnClick(R.id.btn_onLineTest)
    public void onOnLineTestClick(View view){
        mTunnel.write(new OnLineTestPacket().output());
    }

    @OnClick(R.id.btn_readMachineMemoryInfo)
    public void onReadMachineMemoryInfo(View view){
        mTunnel.write(new ReadMachineMemoryPacket().output());
    }

    @OnClick(R.id.btn_readCreditCardInfo)
    public void onReadCreditCardInfo(View view){
        mTunnel.write(new ReadCreditCardInfoPacket(mLastCardInfoId).output());
    }

    @OnClick(R.id.btn_openAutoGate)
    public void onOpenAutoGate(View view){
        mTunnel.write(new SoftOpenGatePacket().output());
    }

    @OnClick(R.id.btn_forceAlwaysOpenAutoGate)
    public void onForceAlwaysOpenAutoGate(View view){
        mTunnel.write(new ForceGateAlwaysOpenPacket().output());
    }

    @OnClick(R.id.btn_closeAutoGate)
    public void onCloseAutoGate(View view){
        mTunnel.write(new ForceGateClosePacket().output());
    }
}
